package org.ligson.fwc.core.entity.constraint;


import org.ligson.fwc.core.dao.BaseDao;
import org.ligson.fwc.core.entity.BasicEntity;
import org.ligson.fwc.core.entity.Constraint;
import org.ligson.fwc.core.enums.ConstraintType;
import org.ligson.fwc.core.util.ServiceLocator;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * Created by ligson on 2017/8/2.
 */
public class UniqueConstraint extends Constraint {
    private Class<? extends BaseDao> daoClazz;

    public UniqueConstraint(String fieldName, Class<? extends BaseDao> clazz) {
        super(fieldName, ConstraintType.Unique);
        daoClazz = clazz;
    }

    @Override
    public boolean valid(Object object, Object fieldValue) {
        if (fieldValue == null) {
            return true;
        }
        BaseDao dao = ServiceLocator.getService(daoClazz);
        try {
            Class<? extends Object> entityClazz = object.getClass();
            Object cond = entityClazz.newInstance();
            Field field = entityClazz.getDeclaredField(getFieldName());
            Method method = entityClazz.getDeclaredMethod("set" + Character.toUpperCase(getFieldName().charAt(0)) + getFieldName().substring(1), field.getType());
            method.invoke(cond, fieldValue);
            BasicEntity basicEntity = dao.findBy((BasicEntity) cond);
            if (basicEntity == null) {
                return true;
            } else {
                String keyName = basicEntity.primaryKey();
                String keyGetMethodName = "get" + Character.toUpperCase(keyName.charAt(0)) + keyName.substring(1);
                Method getMethod = entityClazz.getDeclaredMethod(keyGetMethodName);
                Object basicKey = getMethod.invoke(basicEntity);
                Object key2 = getMethod.invoke(object);
                return Objects.equals(basicKey, key2);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public String errorTip() {
        return "要求唯一";
    }
}
